package mutation;

import java.util.List;

import GA.*;
import util.*;
import Operations.*;
public class ChangeInputValue extends MutationStrategy {

	@Override
	public Chromosome mutate(Chromosome individual) {
		List<Operation> ops =individual.getTest();
		
		boolean hasParams=false;
		for(int i=0;i<ops.size();i++)
			if(ops.get(i) instanceof Invoke){
				Invoke op=(Invoke) ops.get(i);
				final MethodDeclared method =  op.getMethod();
				final Class<?>[] paramsTypes = method.getParameterTypes();
				if(paramsTypes.length!=0)
					hasParams=true;
			}
				
		try {

			while (true &&hasParams) {
				int randNum = ValuesGenerator.getRandomInt(ops.size());
				Operation op = ops.get(randNum);
				if (op instanceof Invoke) {		
//					if(op.toString().contains(".equals")){
//						System.out.println("ChangeInputValue.mutate:"+ op.toString());
//						System.out.println("ChangeInputValue.mutate:"+ individual.toString());
//					}
						boolean commitedChange= mutantMethodParams((Invoke) op,individual);
//					if(op.toString().contains(".equals")){
//						System.out.println("ChangeInputValue.mutate:"+ op.toString());
//						System.out.println("ChangeInputValue.mutate:"+ individual.toString());
//					}
					if(commitedChange)
						break;
				}

			}
		} catch (Throwable e){
			System.err.println("Change Input Value Class:" + e.getMessage());
		}	

		return individual;
	}
	private boolean mutantMethodParams(Invoke op,Chromosome individual) throws Throwable {
		final MethodDeclared method = op.getMethod();
		final Class<?>[] paramsTypes = method.getParameterTypes();
		String[] p = new String[paramsTypes.length];
		String[] preParams=op.getParams();
		boolean commitedChange=false;
		for(int i = 0; i < p.length; i++) {
			Class<?> clz=paramsTypes[i];
			do {
			if(Filter.isPrimitiveOrStringType(clz)){
				p[i] = 	ValuesGenerator.buildValue(clz.getName());
				commitedChange=true;
			}
			else{
//				commitedChange=true;
//				String refs[] = individual.getReferenceFactory().get(clz.getName());//(cName);
//				p[i] =preParams[i];

				if(GAConfig.NumVarCut==1) break;
					p[i] = Operation.generateRef(method,clz, individual.getReferenceFactory(),individual.getCluster());

				commitedChange=true;
			}
			} while (p[i]==preParams[i]);
		}
		if(commitedChange)
			op.setParams(p);
		return true;
	}
	@Override
	public boolean getMutationFlag() {
		return true;
	}
}
